//! Log4rError 单元测试
//!
//! 测试错误类型的功能

use log4r::Log4rError;
use std::io;

/// [P0] 测试 ConfigError 创建和显示
#[test]
fn test_config_error() {
    // GIVEN: 配置错误消息
    let error_msg = "无效的配置格式";

    // WHEN: 创建 ConfigError
    let error = Log4rError::ConfigError(error_msg.to_string());

    // THEN: 错误消息应正确显示
    let display = error.to_string();
    assert!(display.contains("配置错误"));
    assert!(display.contains(error_msg));
}

/// [P0] 测试 IoError 从 std::io::Error 转换
#[test]
fn test_io_error_from() {
    // GIVEN: 一个 std::io::Error
    let io_error = io::Error::new(io::ErrorKind::NotFound, "文件未找到");

    // WHEN: 转换为 Log4rError
    let error: Log4rError = io_error.into();

    // THEN: 应为 IoError 变体
    let display = error.to_string();
    assert!(display.contains("IO 错误"));
    assert!(display.contains("文件未找到"));
}

/// [P0] 测试 AppenderError 创建和显示
#[test]
fn test_appender_error() {
    // GIVEN: Appender 错误信息
    let name = "FileAppender";
    let cause = "无法打开文件";

    // WHEN: 创建 AppenderError
    let error = Log4rError::AppenderError {
        name: name.to_string(),
        cause: cause.to_string(),
    };

    // THEN: 错误消息应包含名称和原因
    let display = error.to_string();
    assert!(display.contains(name));
    assert!(display.contains(cause));
}

/// [P1] 测试 Log4rError Debug 格式化
#[test]
fn test_error_debug() {
    // GIVEN: 各种错误类型
    let errors = vec![
        Log4rError::ConfigError("测试".to_string()),
        Log4rError::AppenderError {
            name: "Test".to_string(),
            cause: "测试原因".to_string(),
        },
    ];

    // WHEN/THEN: 每个错误都应能 Debug 格式化
    for error in errors {
        let debug_str = format!("{:?}", error);
        assert!(!debug_str.is_empty());
    }
}

/// [P1] 测试 IoError 各种类型
#[test]
fn test_io_error_kinds() {
    // GIVEN: 各种 IO 错误类型
    let io_errors = vec![
        io::Error::new(io::ErrorKind::NotFound, "未找到"),
        io::Error::new(io::ErrorKind::PermissionDenied, "权限拒绝"),
        io::Error::new(io::ErrorKind::AlreadyExists, "已存在"),
        io::Error::new(io::ErrorKind::InvalidInput, "无效输入"),
    ];

    // WHEN/THEN: 每种 IO 错误都应能转换
    for io_error in io_errors {
        let error: Log4rError = io_error.into();
        let display = error.to_string();
        assert!(display.contains("IO 错误"));
    }
}

/// [P1] 测试 ConfigError 空消息
#[test]
fn test_config_error_empty_message() {
    // GIVEN: 空错误消息
    // WHEN: 创建 ConfigError
    let error = Log4rError::ConfigError(String::new());

    // THEN: 应成功创建
    let display = error.to_string();
    assert!(display.contains("配置错误"));
}

/// [P2] 测试 AppenderError 空字段
#[test]
fn test_appender_error_empty_fields() {
    // GIVEN: 空字段
    // WHEN: 创建 AppenderError
    let error = Log4rError::AppenderError {
        name: String::new(),
        cause: String::new(),
    };

    // THEN: 应成功创建
    let display = error.to_string();
    assert!(display.contains("Appender"));
}

/// [P2] 测试错误可以作为 Result 返回
#[test]
fn test_error_in_result() {
    // GIVEN: 一个返回 Result 的函数
    fn may_fail(should_fail: bool) -> Result<(), Log4rError> {
        if should_fail {
            Err(Log4rError::ConfigError("失败".to_string()))
        } else {
            Ok(())
        }
    }

    // WHEN/THEN: 应能正确处理 Result
    assert!(may_fail(false).is_ok());
    assert!(may_fail(true).is_err());
}

/// [P2] 测试 ConfigError 支持 Unicode
#[test]
fn test_config_error_unicode() {
    // GIVEN: Unicode 错误消息
    let error_msg = "配置文件 🔧 解析失败 émoji テスト";

    // WHEN: 创建 ConfigError
    let error = Log4rError::ConfigError(error_msg.to_string());

    // THEN: Unicode 应正确保存
    let display = error.to_string();
    assert!(display.contains(error_msg));
}

/// [P0] 测试 AlreadyInitialized 错误变体 (AC-2.3.1, AC-2.3.3)
#[test]
fn test_already_initialized_error() {
    // GIVEN: AlreadyInitialized 错误
    // WHEN: 创建错误
    let error = Log4rError::AlreadyInitialized;

    // THEN: 应正确显示中文错误信息
    let display = error.to_string();
    assert!(display.contains("已初始化"));
    assert_eq!(display, "日志系统已初始化");
}

/// [P0] 测试便捷构造函数 config() (AC-2.3.1)
#[test]
fn test_config_convenience_constructor() {
    // GIVEN: 错误消息
    let msg = "无效的配置格式";

    // WHEN: 使用便捷构造函数
    let error = Log4rError::config(msg);

    // THEN: 应创建 ConfigError 变体并正确显示
    let display = error.to_string();
    assert!(display.contains("配置错误"));
    assert!(display.contains(msg));
}

/// [P0] 测试便捷构造函数 appender() (AC-2.3.1)
#[test]
fn test_appender_convenience_constructor() {
    // GIVEN: Appender 信息
    let name = "FileAppender";
    let cause = "无法打开文件";

    // WHEN: 使用便捷构造函数
    let error = Log4rError::appender(name, cause);

    // THEN: 应创建 AppenderError 变体并正确显示
    let display = error.to_string();
    assert!(display.contains(name));
    assert!(display.contains(cause));
}

/// [P1] 测试 Log4rError 实现 std::error::Error trait (AC-2.3.2)
#[test]
fn test_error_std_trait() {
    // GIVEN: Log4rError 类型
    // WHEN: 检查 Error trait
    // THEN: 应实现 std::error::Error

    fn assert_error<T: std::error::Error>() {}
    assert_error::<Log4rError>();
}
